package com.acme.javaschool.sems.ionio.filetools;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;

import static java.lang.Math.min;

public class NioTools {
    public static boolean copyNio(String fromFilePath, String toFilePath) {
        try (FileChannel in = new FileInputStream(fromFilePath).getChannel();
             FileChannel out = new FileOutputStream(toFilePath).getChannel();
        ) {
            long bytesToBeRead = in.size();

            ByteBuffer readBytes = ByteBuffer.allocate((int) min(in.size(), Integer.MAX_VALUE));
            while (bytesToBeRead > 0) {
                bytesToBeRead -= in.read(readBytes);
                readBytes.flip();
                int bytesWritten = out.write(readBytes);
            }

        } catch (FileNotFoundException e) { e.printStackTrace(); return false;
        } catch (IOException e) { e.printStackTrace(); return false; }

        return true;
    }

    public static int receiveChunkAndPutToFileNio(SocketChannel socketChannel, FileChannel fileChannel, int chunkSize) {
        ByteBuffer buffer = ByteBuffer.allocate(chunkSize);

        try {
            socketChannel.read(buffer);
            buffer.flip();
            return fileChannel.write(buffer);
        } catch (IOException e) { e.printStackTrace(); return 0; }
    }

    public static int readChunkFromFileAndSendNio(FileChannel fileChannel, SocketChannel socketChannel, int chunkSize) {
        ByteBuffer buffer = ByteBuffer.allocate(chunkSize);

        try {
            fileChannel.read(buffer);
            buffer.flip();
            return socketChannel.write(buffer);
        } catch (IOException e) { e.printStackTrace(); return 0; }
    }

    public static long readLong(SocketChannel channel) {
        long n = 0L;

        ByteBuffer buffer = ByteBuffer.allocate(8);
        try {
            channel.read(buffer);
        } catch (IOException e) { e.printStackTrace(); }

        buffer.flip();
        n = buffer.getLong();
        return n;
    }

    public static void writeLong(SocketChannel channel, long n) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(n);
        try {
            buffer.flip();
            channel.write(buffer);
        } catch (IOException e) { e.printStackTrace(); }
    }
}
